﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using LiveGame;

namespace LiveGame.Tests
{
    [TestClass]
    public class BoardTest
    {
        [TestMethod]
        public void SetUpBoard_4Rows8Columns_Test()
        {
            // Setup
            var board = new Board( 4, 8 );

            // Action
            var totalRows = board.Length;
            var totalColumnsOnFirstRow = board [ 0 ].Length;
            var totalColumnsOnSecondRow = board [ 1 ].Length;
            var totalColumnsOnThirdRow = board [ 2 ].Length;
            var totalColumnsOnFourthRow = board [ 3 ].Length;

            // Assert
            Assert.AreEqual( 4, totalRows );
            Assert.AreEqual( 8, totalColumnsOnFirstRow );
            Assert.AreEqual( 8, totalColumnsOnSecondRow );
            Assert.AreEqual( 8, totalColumnsOnThirdRow );
            Assert.AreEqual( 8, totalColumnsOnFourthRow );
        }

        [TestMethod]
        public void SetUpBoard_4Rows8Columns_WithCells_Test()
        {
            // Setup
            var board = new Board( 4, 8 );

            // Action
            var cells = new List<ICoordinate>();

            foreach( IEnumerable<ICoordinate> columns in board )
                foreach( var cell in columns )
                    cells.Add( cell );

            // Assert if the total cells are equal to 32
            Assert.AreEqual( 32, cells.Count );
        }

        [TestMethod]
        [ExpectedException( typeof( ArgumentNullException ) )]
        public void AddNullPiece_ThrowArgumentNullException()
        {
            // Setup
            var board = new Board( 4, 8 );

            try
            {
                // Action
                for( int index = 0; index < board.Length * board [ 0 ].Length; index++ )
                    board.Add( null );
            }
            catch( ArgumentNullException exception )
            {
                // Assert
                Assert.AreEqual( "LiveGame.IPieces", exception.ParamName );
                throw;
            }
        }

        [TestMethod]
        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
        public void AddCell_CoordinateRowOutOfRangeBoardSize_ThrowArgumentOutOfRangeException()
        {
            // Setup
            var board = new Board( 4, 8 );

            // Action
            try
            {
                board.Add( new Cell( true, 5, 0 ) );
            }
            catch( ArgumentOutOfRangeException exception )
            {
                Assert.AreEqual( "piece.Row", exception.ParamName );
                throw;
            }
        }

        [TestMethod]
        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
        public void AddCell_CoordinateColumnOutOfRangeBoardSize_ThrowArgumentOutOfRangeException()
        {
            // Setup
            var board = new Board( 4, 8 );

            // Action
            try
            {
                board.Add( new Cell( true, 0, 9 ) );
            }
            catch( ArgumentOutOfRangeException exception )
            {
                Assert.AreEqual( "piece.Column", exception.ParamName );
                throw;
            }
        }

        [TestMethod]
        [ExpectedException( typeof( ArgumentException ) )]
        public void Add2Cells_AtTheSameCoordinate_ThrowArgumentException()
        {
            // Setup
            var board = new Board( 4, 8 );

            try
            {
                board.Add( new Cell( true, 0, 0 ) );
                board.Add( new Cell( false, 0, 0 ) );
            }
            catch( ArgumentException exception )
            {
                // Assert
                Assert.AreEqual( "Unable to add new piece since the coordinate you are referring to has been allocated by other piece.", exception.Message );
                throw;
            }
        }

        [TestMethod]
        public void AddCells_Tests()
        {
            // Setup
            var board = new Board( 4, 8 );

            // Action
            for( int rowIndex = 0; rowIndex < board.Length; rowIndex++ )
                for( int columnIndex = 0; columnIndex < board [ rowIndex ].Length; columnIndex++ )
                    board.Add( new Cell( true, rowIndex, columnIndex ) );

            // Assert
            foreach( IEnumerable<ICoordinate> columns in board )
                foreach( var cell in columns )
                    Assert.IsNotNull( cell );
        }
        
    }
}
